#include "common.h"
#include "update.h"

#define TCP_UPDATE_PORT			16802
#if 0

#define DATA_HEAD_LENGTH		16
#define MAX_FILE_NUM			8
#define UPDATE_CHECK_ACK_LEN 	36

#define UPDATE_PACKAGE_NUM_OFFSET		0
#define UPDATE_PACKAGE_NUM_SIZE			4
#define UPDATE_PACKAGE_NO_OFFSET		(UPDATE_PACKAGE_NUM_OFFSET + UPDATE_PACKAGE_NUM_SIZE)
#define UPDATE_PACKAGE_NO_SIZE			4
#define UPDATE_PACKAGE_NAME_OFFSET		(UPDATE_PACKAGE_NO_OFFSET + UPDATE_PACKAGE_NO_SIZE)
#define UPDATE_PACKAGE_NAME_SIZE		32
#define UPDATE_PACKAGE_MD5_OFFSET		(UPDATE_PACKAGE_NAME_OFFSET + UPDATE_PACKAGE_NAME_SIZE)
#define UPDATE_PACKAGE_MD5_SIZE			48
#define UPDATE_PACKAGE_VERSION_OFFSET	(UPDATE_PACKAGE_MD5_OFFSET + UPDATE_PACKAGE_MD5_SIZE)
#define UPDATE_PACKAGE_VERSION_SIZE 	32
#define UPDATE_PACKAGE_HEAD_SIZE 		(UPDATE_PACKAGE_NUM_SIZE + UPDATE_PACKAGE_NO_SIZE + UPDATE_PACKAGE_NAME_SIZE + UPDATE_PACKAGE_MD5_SIZE + UPDATE_PACKAGE_VERSION_SIZE)

//创建头部信息
static void CreateProtocolHead(unsigned int nCmdId, char *buf, int nLen)
{
	buf[0] = 0x4D;
	buf[1] = 0x56;
	buf[2] = 0x49;
	buf[3] = 0x53;
	buf[4] = 0x01;
	buf[5] = 0x0;
	buf[6] = nCmdId&0xff;
	buf[7] = (nCmdId>>8)&0xff;
	buf[8] = 0;
	buf[9] = 0;
	buf[10] = nLen&0xff;
	buf[11] = (nLen>>8)&0xff;
	buf[12] = (nLen>>16)&0xff;
	buf[13] = (nLen>>24)&0xff;
	buf[14] =  0;
	buf[15] =  0;	
}

static int TcpDataSend(int nSockfd, const char *pBuf, int nLen)
{
	int nRes = 0;
	int nSendLen = 0;

	if ((nSockfd < 0) || (pBuf == NULL) || (nLen <= 0))
	{
		return -1;	
	}
	
	while (nLen - nRes)
	{
		nSendLen = send(nSockfd, pBuf + nRes, nLen - nRes, 0);
		if(nSendLen <= 0)
		{
			return -1;
		}
		nRes += nSendLen;
	}
	return nLen;
}

static int TcpDataRead(int nSockfd, char *pBuf, int nLen)
{
	int nRet = 0, nRes = 0, nRecvLen = 0;
	fd_set MaxReadFd;
	struct timeval tv;
	
	if ((nSockfd < 0) || (pBuf == NULL) || (nLen <= 0))
	{
		return -1;	
	}

	tv.tv_sec = 10;
	tv.tv_usec = 0;
	FD_ZERO(&MaxReadFd);
	FD_SET(nSockfd, &MaxReadFd);

	while (nLen - nRes) 
	{
		nRet = select(nSockfd + 1, &MaxReadFd, NULL, NULL, &tv);
		if (nRet < 0)
		{						
			return -1;
		}

		nRecvLen = recv(nSockfd, pBuf + nRes, nLen - nRes , 0);
		if(nRecvLen <= 0)
		{			
			return -1;
		}		
		nRes += nRecvLen;	
	}
	return nLen;
}

static int CheckProtocolHead(char *pHeadBuf, unsigned int *pCmdId, unsigned int *pLen)
{
	unsigned int nVersion = 0;
	unsigned int nCmdId =0;
	unsigned int nDataLen = 0;

	if ((pHeadBuf == NULL) || (pLen == NULL))
	{
		DEBUG("pointer pHeadBuf or pointer pLen is NULL \n");
		return -1;
	}
	
	//包头
	if ((pHeadBuf[0] == 0x4D) && (pHeadBuf[1] == 0x56) && (pHeadBuf[2] == 0x49) && (pHeadBuf[3] == 0x53))
	{
		nVersion = (unsigned int)(pHeadBuf[4] | (pHeadBuf[5]<<8));
		if (nVersion == 0x0001)
		{
			nCmdId = (unsigned int)(pHeadBuf[6] | (pHeadBuf[7]<<8));		
			nDataLen = (unsigned int)(pHeadBuf[10] | (pHeadBuf[11]<<8) | (pHeadBuf[12]<<16) | (pHeadBuf[13]<<24));
			//DEBUG("g_cmdId=0x%x,g_DataLen=%d\n",g_cmdId,g_DataLen);		
			if(nDataLen < 0)
			{
				DEBUG("nDataLens is error:0x%x\n",nDataLen);	
				return -1;
			}	
			else
			{
				*pLen = nDataLen;
				*pCmdId = nCmdId;
			}
		}
		else
		{
			DEBUG("Version is error:0x%x\n", nVersion);	
			return -1;
		}			
	}
	else
	{
		DEBUG("DataHead is not 4D 56 49 53: 0x%x 0x%x 0x%x 0x%x\n", pHeadBuf[0], pHeadBuf[1], pHeadBuf[2], pHeadBuf[3]);
		return -1;
	}
	
	return 0;
}

int CreateSocketFd(void)
{
	struct sockaddr_in ServerAddr;
	int nSockFd = 0;
	int nVal = 1;
	int nKeepAlive = 1; // 开启keepalive属性
	int nKeepIdle = 60; // 如该连接在60秒内没有任何数据往来,则进行探测
	int nKeepInterval = 5; // 探测时发包的时间间隔为5 秒
	int nKeepCount = 3; // 探测尝试的次数.如果第1次探测包就收到响应了,则后2次的不再发.

	if((nSockFd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
	{
		perror("create socket error:");	
		return -1;	
	}
	else
	{
		DEBUG("create socket sockfd = %d\n", nSockFd);
	}
	
	memset((char *)&ServerAddr, 0, sizeof(ServerAddr));
	ServerAddr.sin_family = AF_INET;
	ServerAddr.sin_port = htons(TCP_UPDATE_PORT);
	ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);	
	if (setsockopt(nSockFd, SOL_SOCKET, SO_REUSEADDR, &nVal, sizeof(int)) < 0)
	{
		perror("setsockopt");
		return -1;
	}
	if (bind(nSockFd, (struct sockaddr *)&ServerAddr, sizeof(ServerAddr)) < 0)
	{
		perror("bind error:");	
		return -1;	
	}

	if (setsockopt(nSockFd, SOL_SOCKET, SO_KEEPALIVE, (void *)&nKeepAlive, sizeof(int)) < 0)
	{
		perror("setsockopt");
		return -1;
	}
	if (setsockopt(nSockFd, SOL_TCP, TCP_KEEPIDLE, (void*)&nKeepIdle, sizeof(int)) < 0)
	{
		perror("setsockopt");
		return -1;
	}
	if (setsockopt(nSockFd, SOL_TCP, TCP_KEEPINTVL, (void *)&nKeepInterval, sizeof(int)) < 0)
	{
		perror("setsockopt");
		return -1;
	}
	if (setsockopt(nSockFd, SOL_TCP, TCP_KEEPCNT, (void *)&nKeepCount, sizeof(int)) < 0)
	{
		perror("setsockopt");
		return -1;
	}
	if (listen(nSockFd, 128) < 0)
	{
		perror("listen failed:");
		return -1;		
	}
	DEBUG("Create update socket OK, listenning ......\n");

	return nSockFd;
}

void mvGetSoftVerFive(char *pSoftVerOut,char *pSoftVerin)
{
	int i = 0;
	const char chData[2] = ".";
	char *chToken =NULL;
		
	/*获取第一个字符串	*/
	chToken = strtok(pSoftVerin,chData);
	
	//获取其他字符串
	while(chToken != NULL)
	{
		sprintf(pSoftVerOut+strlen(pSoftVerOut),"%s.",chToken);
				
		chToken = strtok(NULL,chData);
		
		i++;
		
		if	(i==4)
		{
			sprintf(pSoftVerOut+strlen(pSoftVerOut),"%s",chToken);
			break;
		}
	}
	
	return;
}


int GetCurVersion(int nConnectFd)
{
	int nLen = 0;
	int nSendLen = 0;
	int nRet = 0;
	DeviceInfoPart tInfoPart;
	char szSendBuf[1024] = {0};	
	char chSoftwareVerFive[32];
	memset(chSoftwareVerFive,0,32);

	nRet = GetInfoPart(&tInfoPart);
	if ((nRet != 0) || (CheckDeviceInfo(&tInfoPart) == -1) || ((tInfoPart.nBootFlag != 0) && (tInfoPart.nBootFlag != 1)))
	{
		DEBUG("nRet:%d tInfoPart.nBootFlag:%d\n", nRet, tInfoPart.nBootFlag);
		memset(&tInfoPart, 0, sizeof(DeviceInfoPart));
		nRet = 1;
	}
	else
	{
		DEBUG("now get current version\n");
	}

	nLen = 16;
	mvGetSoftVerFive(chSoftwareVerFive,tInfoPart.aCoreVer[tInfoPart.nBootFlag].szHardwareVer);
	memcpy(szSendBuf+nLen,chSoftwareVerFive,32);
	
	nLen += 32;
	memset(chSoftwareVerFive,0,32);
	mvGetSoftVerFive(chSoftwareVerFive,tInfoPart.aCoreVer[tInfoPart.nBootFlag].szSoftwareVer);
	memcpy(szSendBuf+nLen,chSoftwareVerFive,32);
						
	nLen += 32;
	memcpy(szSendBuf + nLen, "BOOT.bin", 32);
			
	nLen += 32;
	memcpy(szSendBuf + nLen, tInfoPart.szBootVersion, 32);
			
	nLen += 32;
	memcpy(szSendBuf + nLen, "devicetree.dtb", 32);
			
	nLen += 32;
	memcpy(szSendBuf + nLen, tInfoPart.aCoreVer[tInfoPart.nBootFlag].szDtbVer, 32);
			
	nLen += 32;
	memcpy(szSendBuf + nLen, "image.ub", 32);
			
	nLen += 32;
	memcpy(szSendBuf + nLen, tInfoPart.aCoreVer[tInfoPart.nBootFlag].szKernelVer, 32);
			
	nLen += 32;
	memcpy(szSendBuf + nLen, "urootfs.cpio.lz4", 32);
			
	nLen += 32;
	memcpy(szSendBuf + nLen, tInfoPart.aCoreVer[tInfoPart.nBootFlag].szRootfsVer, 32);

	nLen += 32;
	memcpy(szSendBuf + nLen, "fpga.bin", 32);
			
	nLen += 32;
	memcpy(szSendBuf + nLen, tInfoPart.aCoreVer[tInfoPart.nBootFlag].szFpgaVer, 32);

	nLen += 32;
	memcpy(szSendBuf + nLen, "weight.bin", 32);
			
	nLen += 32;
	memcpy(szSendBuf + nLen, tInfoPart.aCoreVer[tInfoPart.nBootFlag].szWeightVer, 32);

	nLen += 32;
	memcpy(szSendBuf + nLen, "mcu.elf", 32);
			
	nLen += 32;
	memcpy(szSendBuf + nLen, tInfoPart.aCoreVer[tInfoPart.nBootFlag].szMcuVer, 32);

	nLen += 32;
	memcpy(szSendBuf + nLen, "mv_app", 32);
			
	nLen += 32;
	memcpy(szSendBuf + nLen, tInfoPart.aCoreVer[tInfoPart.nBootFlag].szAppVer, 32);

	nLen += 32;
	memcpy(szSendBuf + nLen, "watchdog", 32);
			
	nLen += 32;
	memcpy(szSendBuf + nLen, tInfoPart.szWatchDogVer, 32);

	nLen += 32;
					
	CreateProtocolHead(0x0300, szSendBuf, nLen - 16);  //组返回消息头部信息
	nSendLen = TcpDataSend(nConnectFd, szSendBuf, nLen);
	if(nSendLen != nLen)
	{
		DEBUG("send update file ack error!\n");	
		nRet = -1;
	}
	return nRet;			
}
int BootUpdateTask(int nConnectFd, char *pBuf, int nLen)
{
	int nRet = 0;
	int nFileLen = 0;
	int nPackageNum = 0;
	int nPackageNo = 0;
	int nCount = 600;
	char szMd5Buf[48];
	char szFileVersion[32];
	char szFileName[32];
	char *pFileBuf = NULL;
	char aSendBuf[1024] = {0};
	int nSendLen = 0;
	int nProgress = -1;
	
	//解析升级包头部信息
	nPackageNum = *(unsigned int *)(pBuf);
	nPackageNo = *(unsigned int *)(pBuf + UPDATE_PACKAGE_NO_OFFSET);
	memcpy(szFileName, pBuf + UPDATE_PACKAGE_NAME_OFFSET, UPDATE_PACKAGE_NAME_SIZE);
	memcpy(szMd5Buf, pBuf + UPDATE_PACKAGE_MD5_OFFSET, UPDATE_PACKAGE_MD5_SIZE);
	memcpy(szFileVersion, pBuf + UPDATE_PACKAGE_VERSION_OFFSET, UPDATE_PACKAGE_VERSION_SIZE);
	DEBUG("PackageNum %d PackageNo %d FileName is %s Md5 %s Version %s\n", \
		nPackageNum, nPackageNo, szFileName, szMd5Buf, szFileVersion);
	
	pFileBuf = pBuf + UPDATE_PACKAGE_HEAD_SIZE;
	nFileLen = nLen - UPDATE_PACKAGE_HEAD_SIZE;
	if (!strcmp((const char *)szFileName, "update.tar.gz"))
	{	
		system("rm -rf /tmp/*");
		nRet = SaveDdrFile("/tmp/tmp_update.tar.gz", pFileBuf, nFileLen);
		if (nRet != 0)
		{
			goto failed;
		}
	}
	else
	{
		DEBUG("file name:%s is error!\n", szFileName);
		goto failed;
	}

	SetUpdateProgress(15);
	rename("/tmp/tmp_update.tar.gz", "/tmp/update.tar.gz");
	while (1)
	{
		sleep(1);
		nProgress = GetUpdateProgress();
failed:
		CreateProtocolHead(0x0501, aSendBuf, UPDATE_CHECK_ACK_LEN);
		memcpy(aSendBuf + 16, szFileName, 32);   //copy file name to ack
		*(unsigned int *)(aSendBuf + 48) = nProgress;
		nSendLen = TcpDataSend(nConnectFd, aSendBuf, UPDATE_CHECK_ACK_LEN + DATA_HEAD_LENGTH);
		if(nSendLen != (UPDATE_CHECK_ACK_LEN + DATA_HEAD_LENGTH))
		{
			DEBUG("send update file ack error!\n");	
			nRet = -1;
			break;
		}
		if (nProgress == 100 || nProgress < 0)
		{
			nRet = 0;
			break;
		}
	}
	return nRet;
}

int ProcessCommand(int nConnectFd, int nCmdId, char *pBuf, int nLen)
{
	int nRet = 0;

	switch (nCmdId)
	{
		case 0x300:
			nRet = GetCurVersion(nConnectFd);
			break;
		case 0x500:
			nRet = BootUpdateTask(nConnectFd, pBuf, nLen);
			break;
		default:
			DEBUG("don't know cmdId is:0x%x!\n", nCmdId);
			break;
	}	
	return nRet;
}

void *BootNetUpdateServer(void *arg)
{
	socklen_t ClientLen;
	struct sockaddr_in ClientAddr;
	int nSockFd = 0;
	int nConnectFd = 0;
	int nHeadLen = 0;
	unsigned int nCmdId = 0;
	unsigned int nPayLoadLen = 0;
	int nRecvLen = 0;
	char aBuff[64];
	char aHeadBuf[64];
	char *pFileBuf = NULL;
	int nRet = 0;	

	nSockFd = CreateSocketFd();
	if (nSockFd < 0)
	{
		DEBUG("Create Socket failed!\n");
		return NULL;
	}

	ClientLen = sizeof(ClientAddr);
	while (1)
	{
		if(nConnectFd <= 0)
		{
			DEBUG("update wait connect!\n");
			nConnectFd = accept(nSockFd, (struct sockaddr*)&ClientAddr, &ClientLen);
			if (nConnectFd > 0)
			{
				inet_ntop(AF_INET, &ClientAddr.sin_addr, aBuff, sizeof(aBuff));
				DEBUG("Now cli %s connect update, connfd = %d\n", aBuff, nConnectFd);	
			}
			else
			{
				continue;
			}
		}	

		memset(aHeadBuf, 0, 64);
		DEBUG("update wait recv!\n");
		nHeadLen = TcpDataRead(nConnectFd, aHeadBuf, DATA_HEAD_LENGTH);
		DEBUG("update nHeadLen = %d\n", nHeadLen);
		if(nHeadLen <= 0)
		{
			DEBUG("Recv %s message error!connfd=%d\n", aBuff, nConnectFd);		
			close(nConnectFd);	
			nConnectFd = 0;
			continue;
		}

		nRet = CheckProtocolHead(aHeadBuf, &nCmdId, &nPayLoadLen);	
		if(nRet < 0)   //包头信息检验失败
		{
			DEBUG("check data head error!close connfd=%d\n",nConnectFd);
			close(nConnectFd);	
			nConnectFd = 0;
			continue;
		}
		if (nPayLoadLen > 0)
		{
			pFileBuf = (char *)malloc(nPayLoadLen + 64);
			if (pFileBuf == NULL)
			{
				DEBUG("malloc pFileBuf is error!\n");						
				close(nConnectFd);
				nConnectFd = 0;
				continue;
			}
			memset((char *)pFileBuf, 0, nPayLoadLen + 64);
			nRecvLen = TcpDataRead(nConnectFd, pFileBuf, nPayLoadLen);	
			DEBUG("update payload len=%d, recvlen = %d\n",nPayLoadLen, nRecvLen);	
			if (nRecvLen < 0)
			{						
				close(nConnectFd);		
				nConnectFd = 0;
				//重启设备
				continue;
			}
		}

		nRet = ProcessCommand(nConnectFd, nCmdId, pFileBuf, nPayLoadLen);
		if (nRet < 0)
		{	
			close(nConnectFd);		
			nConnectFd = 0;
		}
		if (pFileBuf != NULL)
		{
			free(pFileBuf);
			pFileBuf = NULL;
		}
	}
}

void xdsRecoveTest(char retOk)
{
	if (retOk) {
		system("unzip -q -d /ota/img /ota/cul/zip/ota.zip");
	} 
}
#endif

void FillProgressMsgData(UpgradeInfo *proceInfo, MvUpdate2MvOtaNetData *msg)
{
	DeviceInfoPart tInfo;
	int nRet;
	if ((proceInfo == NULL) || (msg == NULL)) {
		return;
	}
	memset(proceInfo, 0, sizeof(UpgradeInfo));
	memset(msg, 0, sizeof(MvUpdate2MvOtaNetData));

	proceInfo->nStatus = GetOtaState();
	proceInfo->nValue = GetUpdateProgress();

	nRet = GetInfoPart(&tInfo);
	if (nRet < 0) {
		DEBUG("get info part failed\n");
	}

	if (tInfo.szReserved[8] == OTA_REBOOT && (tInfo.szReserved[4] == OTA_UPDATE)) {
		proceInfo->nReboot = 1;
	} else {
		proceInfo->nReboot = 0;
	}
	
	msg->nType = 0x1;
	msg->nDataLen = sizeof(UpgradeInfo);
	msg->nCmd = E_UpgradeMvUpdate2MvOtaCmd_UpgradeStatusResp;
	memcpy(&msg->data[0], proceInfo, sizeof(UpgradeInfo));
}

void FillRqsMsgData(UpgradeInfo *proceInfo, MvUpdate2MvOtaNetData *msg, char type)
{
	char state = type;
	BsdiffInfo xcdInfo;
	int nRet;
	
	if ((proceInfo == NULL) || (msg == NULL)) {
		return;
	}
	memset(proceInfo, 0, sizeof(UpgradeInfo));
	memset(msg, 0, sizeof(MvUpdate2MvOtaNetData));

	msg->nType = 0x1;
	if (state == RQS_OTA_FILE) {
		msg->nDataLen = sizeof(xcdInfo);
		memset(&xcdInfo, 0, sizeof(xcdInfo));
		memcpy(&xcdInfo.sBaselinePath[0], "/ota/img", strlen("/ota/img"));
		memcpy(&xcdInfo.sPackagePath[0], "/ota/cur/xcd/inc.zip", strlen("/ota/cur/xcd/inc.zip"));
		memcpy(&xcdInfo.sCachePath[0], "/ota/data", strlen("/ota/data"));
		memcpy(&msg->data[0], &xcdInfo, sizeof(xcdInfo));
		msg->nCmd = E_UpgradeMvUpdate2MvOtaCmd_BsdiffReq;
	} else {
		proceInfo->nStatus = GetOtaState();
		proceInfo->nValue = GetUpdateProgress();
		proceInfo->nReboot = 0;
		memcpy(&msg->data[0], proceInfo, sizeof(UpgradeInfo));
		msg->nDataLen = sizeof(UpgradeInfo);
		msg->nCmd = E_UpgradeMvUpdate2MvOtaCmd_RebootReq;
		/* save reboot flag */
		nRet = SetOtaRebootFlag();
		if (nRet < 0) {
			DEBUG("SetOtaRebootFlag failed, nRet:%d\n", nRet);
		}
		MySystem("sync ");
		sleep(1);
	}
}

int CreateSocketFd(void)
{
	struct sockaddr_un serverAddr;
	int nSockFd = 0;
	//int nVal = 1;
	int nKeepAlive = 1; // 开启keepalive属性
	//int nKeepIdle = 60; // 如该连接在60秒内没有任何数据往来,则进行探测
	//int nKeepInterval = 5; // 探测时发包的时间间隔为5 秒
	//int nKeepCount = 3; // 探测尝试的次数.如果第1次探测包就收到响应了,则后2次的不再发.

	//udp
	if((nSockFd = socket(AF_LOCAL, SOCK_DGRAM/*SOCK_STREAM*/, 0)) < 0 )
	{
		DEBUG("create socket error \n");	
		return -1;	
	}
	else
	{
		DEBUG("create udp socket sockfd = %d\n", nSockFd);
	}
	memset((char *)&serverAddr, 0, sizeof(serverAddr));
	serverAddr.sun_family = AF_LOCAL;
    strcpy(serverAddr.sun_path, "/tmp/MvUpdateSocket");
	
	if (0 == access(serverAddr.sun_path, F_OK))
    {
        remove(serverAddr.sun_path);
    }
	if (bind(nSockFd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0)
	{
		DEBUG("bind error \n");	
		return -1;	
	}
#if 0

	if (setsockopt(nSockFd, SOL_SOCKET, SO_KEEPALIVE, (void *)&nKeepAlive, sizeof(int)) < 0)
	{
		DEBUG("setsockopt");
		return -1;
	}
	if (setsockopt(nSockFd, SOL_TCP, TCP_KEEPIDLE, (void*)&nKeepIdle, sizeof(int)) < 0)
	{
		perror("setsockopt");
		return -1;
	}
	if (setsockopt(nSockFd, SOL_TCP, TCP_KEEPINTVL, (void *)&nKeepInterval, sizeof(int)) < 0)
	{
		perror("setsockopt");
		return -1;
	}
	if (setsockopt(nSockFd, SOL_TCP, TCP_KEEPCNT, (void *)&nKeepCount, sizeof(int)) < 0)
	{
		perror("setsockopt");
		return -1;
	}
	if (listen(nSockFd, 128) < 0)
	{
		perror("listen failed:");
		return -1;		
	}
	DEBUG("Create update socket OK, listenning ......\n");
	#endif

	return nSockFd;
}

void *CreatUdpUpdateServer(void *arg)
{
	socklen_t ClientLen;
	struct sockaddr_un clientaddr;
	int nSockFd = 0;
	int nRet = 0;	
	int progress = 0;
	char state;
	static int preProgress = 0;
	static char preOtaStatus = E_OTAUpgradeStatusInit;
	MvUpdate2MvOtaNetData msg;
	UpgradeInfo proceInfo;

	nSockFd = CreateSocketFd();
	if (nSockFd < 0) {
		DEBUG("Create Socket failed!\n");
		return NULL;
	}
	ClientLen = sizeof(clientaddr);

loop:

	//wait clent for handshake
	memset(&msg, 0, sizeof(msg));
	nRet = recvfrom(nSockFd, &msg, sizeof(msg), 0, ((struct sockaddr *)&clientaddr), &ClientLen);
	if (nRet <= 0) {
		DEBUG("recv err, nRet:%d\n", nRet);
		goto loop;
	} else if ((msg.nType != 0x2) || (msg.nCmd != E_UpgradeMvOta2MvUpdateCmd_HandshakeReq)) {
		DEBUG("recv date err, nRet:%d, nType:%d, nCmd:%d\n", nRet, msg.nType, msg.nCmd);
		goto loop;
	} else {
		DEBUG("\n recv handshake cmd...\n");
	}

	FillProgressMsgData(&proceInfo, &msg);
	
	sendto(nSockFd, &msg, sizeof(msg), 0, (struct sockaddr *)&clientaddr, sizeof(clientaddr));
	if ((proceInfo.nStatus != E_OTAUpgradeStatusIdle) && (proceInfo.nStatus != E_OTAUpgradeStatusUpgrading)) {
		DEBUG("status is mismatch...\n", proceInfo.nStatus);
		goto loop;
	}
	if (proceInfo.nStatus == E_OTAUpgradeStatusUpgrading) {
		DEBUG("power on after send reboot cmd...\n");
		goto send; /* after ota reboot, need to update process */
	}

	while (1) {
		memset(&msg, 0, sizeof(msg));
		DEBUG("wait for client cmd......\n");
		nRet = recvfrom(nSockFd, &msg, sizeof(msg), 0, ((struct sockaddr *)&clientaddr), &ClientLen);
		//客户端关闭时，读取数据个数为0
		if(nRet == 0) {
			DEBUG("nSockFd:%d read over\n", nSockFd);
			continue;
		}
		if(nRet < 0) {
			DEBUG("read failed, nRet:%d\n", nRet);	
			continue;
		}
		//check rev msg
		if ((msg.nType == 0x2) && (msg.nCmd == E_UpgradeMvOta2MvUpdateCmd_StartUpgradeReq)) {
			state = GetOtaState();
			if (state == E_OTAUpgradeStatusIdle) {
				/* only ota statue is idel, then start ota ...*/
				SetRequestState(RQS_OTA_START);
			} else {
				continue;
			}
		} else if ((msg.nType == 0x2) && (msg.nCmd == E_UpgradeMvOta2MvUpdateCmd_BsdiffResp) && (msg.nDataLen == sizeof(BsdiffProcessStatus))) {
			if (msg.data[1] == E_BsdiffStatusSuccessful) { /* msg.data[1] = BsdiffProcessStatus.nStatus */
				SetRequestState(RCV_OTA_FILE_OK);
				DEBUG("xcd recovery ok, data[0]:%d, nDataLen:%d\n", msg.data[1], msg.nDataLen);
			} else if (msg.data[1] == E_BsdiffStatusFailed) {
				SetRequestState(RCV_OTA_FILE_FAIL);
				DEBUG("xcd recovery fail, data[0]:%d, nDataLen:%d\n", msg.data[1], msg.nDataLen);
			} else {
				DEBUG("date is mismatch, data[1]:%d, nDataLen:%d\n", msg.data[1], msg.nDataLen);
				SetRequestState(RCV_OTA_FILE_DOING);
				continue;
			}
		} else {
			DEBUG("msg is mismatch, data[0]:%d, nDataLen:%d\n", msg.data[0], msg.nDataLen);
			continue;
		}

send:
		//send x% and ota state to clent, meybe need to send request for full ota file. 
		for ( ; ;) {
			state = GetRequestState();
			if (state == RQS_OTA_FILE || state == RQS_OTA_REBOOT) {
				FillRqsMsgData(&proceInfo, &msg, state);
				nRet = sendto(nSockFd, &msg, sizeof(msg), 0, (struct sockaddr *)&clientaddr, sizeof(clientaddr));
				if (nRet == -1) {
					DEBUG("send failed, nRet:%d\n", nRet);
				} else if (state == RQS_OTA_FILE) {
					DEBUG("wait for all ota file is prepared...\n");
					break;
				} else if (state == RQS_OTA_REBOOT) {
					DEBUG("wait to reboot soc\n");
				}
			}
			state = GetOtaState();
			progress = GetUpdateProgress();
			if ((preProgress != progress) || (state != preOtaStatus)) {
				preProgress = progress;
				preOtaStatus = state;
				DEBUG("update state:%d, progress:%d \n", (int)state, progress);

				FillProgressMsgData(&proceInfo, &msg);
				if ((state == E_OTAUpgradeStatusFailed) || (state == E_OTAUpgradeStatusSuccessful)) {
					MySystem("sync ");
					sleep(1);
				}
			
				nRet = sendto(nSockFd, &msg, sizeof(msg), 0, (struct sockaddr *)&clientaddr, sizeof(clientaddr));
				if (nRet == -1) {
					DEBUG("send failed, nRet:%d\n", nRet);
				}
				if ((state == E_OTAUpgradeStatusFailed) || (state == E_OTAUpgradeStatusSuccessful)) {
					/* it can receive next ota msg */
					break;
				}
			}
			usleep(100000);
		}		
	}
	close(nSockFd);
}

int UpdateServerInit()
{
	int err = 0;
	pthread_t  _pThreadUpdateServerID;
	
	//创建升级处理线程
	err = pthread_create(&_pThreadUpdateServerID, NULL, CreatUdpUpdateServer/*BootNetUpdateServer*/, NULL);
	if (err != 0)
    {
    	DEBUG("can't create thread:%s\n",strerror(err));
        return -1;
    }
	pthread_detach(_pThreadUpdateServerID);
	
	return 0;
}

